package com.atguigu.auth.service.impl;

import com.atguigu.auth.mapper.SysMenuMapper;
import com.atguigu.auth.service.SysMenuService;
import com.atguigu.auth.service.SysRoleMenuService;
import com.atguigu.auth.utils.MenuHelper;
import com.atguigu.common.config.exception.GuiguException;
import com.atguigu.common.result.Result;
import com.atguigu.model.system.SysMenu;
import com.atguigu.model.system.SysRoleMenu;
import com.atguigu.vo.system.AssginMenuVo;
import com.atguigu.vo.system.MetaVo;
import com.atguigu.vo.system.RouterVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.sql.Array;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2024-01-19
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
    public final SysRoleMenuService roleMenuService;

    public SysMenuServiceImpl(SysRoleMenuService roleMenuService) {
        this.roleMenuService = roleMenuService;
    }

    /**
     * 根据用户id获取用户可以操作的菜单列表
     *
     * @param userId userid
     * @return 菜单列表
     */
    @Override
    public List<RouterVo> findUserMenuListByUserId(Long userId) {
        List <SysMenu> sysMenuList = this.getMenuList(userId);
        // 构建树行结构
        final List<SysMenu> sysMenus = MenuHelper.buildTree(sysMenuList);
        // 构建成所需的路由结构
        return this.buildRouter(sysMenus);
    }

    private List<SysMenu> getMenuList(Long userId) {
        if (userId == 1) {
            // 管理员 查询所有菜单
            final LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysMenu::getStatus, 1);
            return  baseMapper.selectList(queryWrapper);
        }
        // 非管理员 查询用户可操作的菜单
        return  baseMapper.findMenuListByUserId(userId);
    }

    /**
     * 构建成所需的路由结构
     * @param sysMenus 菜单列表
     */
    private List<RouterVo> buildRouter(List<SysMenu> sysMenus) {
        final ArrayList<RouterVo> routers = new ArrayList<>();
        for (SysMenu menu : sysMenus) {
            final RouterVo router = new RouterVo();
            // 路由路由参数
            this.setRouteParams(router, menu, false);
            // 创建下级菜单
            List<SysMenu> children = menu.getChildren();
            //如果当前是菜单，需将按钮对应的路由加载出来，如：“角色授权”按钮对应的路由在“系统管理”下面
            if(menu.getType() ==  1){
                // 查询所有隐藏菜单
                final List<SysMenu> hideMenus = children.stream().filter(item -> StringUtils.isEmpty(item.getComponent())).collect(Collectors.toList());
                for (SysMenu hideMenu : hideMenus) {
                    final RouterVo hideRoute = new RouterVo();
                    //设置对应路由参数
                    this.setRouteParams(hideRoute, hideMenu, true);
                    routers.add(hideRoute);
                }

            }else{
                if(CollectionUtils.isEmpty(children)){
                    if(!children.isEmpty()) {
                        router.setAlwaysShow(true);
                    }
                    // 递归设置路由菜单
                    router.setChildren(buildRouter(children));
                }
            }
            routers.add(router);
        }
        return routers;
    }
    /**
     * 设置对应路由信息
     */
    public void setRouteParams(RouterVo router,SysMenu menu,Boolean isHidden){
        router.setHidden(isHidden);
        router.setAlwaysShow(false);
        router.setPath(getRouterPath(menu));
        router.setComponent(menu.getComponent());
        router.setMeta(new MetaVo(menu.getName(), menu.getIcon()));
    }

    /**
     * 获取路由地址
     * @param menu 菜单信息
     * @return 路由地址
     */
    public String getRouterPath(SysMenu menu) {
        String routerPath = "/" + menu.getPath();
        if(menu.getParentId().intValue() != 0) {
            routerPath = menu.getPath();
        }
        return routerPath;
    }

    /**
     * 根据用户id获取用户可操作菜单列表
     * @param userId  userId
     */
    @Override
    public List<String> findUserPermsByUserId(Long userId) {
        List <SysMenu> menuList = this.getMenuList(userId);
        // 获取菜单中按钮权限并返回
        return menuList.stream()
                .filter(menu -> menu.getType() == 2 && !menu.getPerms().isEmpty())
                .map(SysMenu::getPerms)
                .collect(Collectors.toList());
    }

    /**
     * 所有菜单和角色分配菜单
     * @param roleId 角色id
     */
    // 查询所有菜单和角色分配的菜单 只查询菜单 status = 1
    // 根据角色id roleId 查询角色菜单关系表里面 角色id对应所有的菜单id
    // 根据获取的菜单id获取对应菜单对象
    // 拿着菜单id和所有菜单集合里面的id进行比较，如果相同进行封装
    @Override
    public Result<Object> doRoleMenu(long roleId) {
        LambdaQueryWrapper<SysMenu> menuQueryWrapper = new LambdaQueryWrapper<>();
        menuQueryWrapper.eq(SysMenu::getStatus, 1);
        // 所有菜单集合
        List<SysMenu> menuList = baseMapper.selectList(menuQueryWrapper);

        // 查询角色对应的菜单
        LambdaQueryWrapper<SysRoleMenu> roleMenuLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roleMenuLambdaQueryWrapper.eq(SysRoleMenu::getRoleId, roleId);
        List<SysRoleMenu> list = roleMenuService.list(roleMenuLambdaQueryWrapper);
        // 当前角色下菜单id集合
        List<Long> collect = list.stream().map(SysRoleMenu::getMenuId).collect(Collectors.toList());
        for (SysMenu menu : menuList) {
            // 将角色下已有菜单设置为选中状态
            menu.setSelect(collect.contains(menu.getId()));
        }
        return Result.ok(menuList);
    }

    /**
     * 角色分配菜单
     * @param menuVo menuVo
     * @return Result
     */
    @Override
    public Result<Object> assignMenus(AssginMenuVo menuVo) {
        // 如果角色有分配过菜单先删除已有菜单
        LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysRoleMenu::getRoleId, menuVo.getRoleId());
        roleMenuService.remove(queryWrapper);
        // 分配新的角色下菜单
        for (Long menuId : menuVo.getMenuIdList()) {
            SysRoleMenu sysRoleMenu = new SysRoleMenu();
            sysRoleMenu.setMenuId(menuId);
            sysRoleMenu.setRoleId(menuVo.getRoleId());
            roleMenuService.save(sysRoleMenu);
        }
        return Result.ok();
    }


    /**
     * menu delete
     *
     * @param id the id of the menu
     */
    @Override
    public void removeMenuById(long id) {
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getParentId, id);
        // 查询是否有对应子菜单
        Integer count = baseMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new GuiguException(201, "请先删除对应子菜单");
        }
        // 删除菜单数据
        baseMapper.deleteById(id);
    }

    /**
     * 菜单树
     *
     * @return Result
     */
    @Override
    public List<SysMenu> tree() {
        // 查询所有菜单
        List<SysMenu> menuList = baseMapper.selectList(null);
        System.out.println(menuList);
        return MenuHelper.buildTree(menuList);
    }
}
